<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  
  
  <link rel="shortcut icon" href="../../img/favicon.ico">
  <title>Components - COROS Documentation</title>
  <link rel="stylesheet" href="../../css/theme.css" />
  <link rel="stylesheet" href="../../css/theme_extra.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "Components";
    var mkdocs_page_input_path = "guides/03_components.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="../../js/jquery-2.1.1.min.js" defer></script>
  <script src="../../js/modernizr-2.8.3.min.js" defer></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script> 
  
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href="../.." class="icon icon-home"> COROS Documentation</a>
        <div role="search">
  <form id ="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" title="Type search term here" />
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../..">Home</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">About</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../COPYRIGHT/">Copyright</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../LICENSE/">License</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Beginner's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../tutorials/01_getting_started/">Getting Started</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Hitchker's Guide to:</span></p>
                <ul class="current">
                    <li class="toctree-l1"><a class="reference internal" href="../01_coroutines/">Coroutines</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../02_event_queues/">Event Queues</a>
                    </li>
                    <li class="toctree-l1 current"><a class="reference internal current" href="./">Components</a>
    <ul class="current">
    <li class="toctree-l2"><a class="reference internal" href="#babys-first-component-heartbeat">Baby's first component: heartbeat</a>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#what-precisely-is-a-component">What, precisely, is a "component"?</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#is-that-really-all-there-is">Is that really all there is?</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#message-what-now">Message what now?</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#anything-else">Anything else?</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#a-more-realistic-heartbeat">A more realistic heartbeat</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#what-have-you-done">What have you done!?</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#so-whats-the-point">So what's the point?</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#this-is-why-we-have-comp_define">This is why we have COMP_DEFINE()</a>
    </li>
    </ul>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Technocrat's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/01_co/">co.h</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/02_evq/">evq.h</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/03_comp/">comp.h</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Technomancer's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../architecture/01_coroutines/">Coroutines</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../architecture/02_event_queues/">Event Queues</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../architecture/03_porting/">Porting</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="../..">COROS Documentation</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="../..">Docs</a> &raquo;</li>
    
      
        
          <li>The Hitchker's Guide to: &raquo;</li>
        
      
    
    <li>Components</li>
    <li class="wy-breadcrumbs-aside">
      
    </li>
  </ul>
  
  <hr/>
</div>
          <div role="main">
            <div class="section">
              
                <h1 id="the-hitchhikers-guide-to-components">The Hitchhiker's Guide to  Components</h1>
<p>The COMP portion of COROS was the result of a lot of thinking through of the implications of CO and EVQ as relates to systems design.  Eventually it coalesced into an opinionated architecture that led to easier code to reason about, to move from project to project, and to dynamically update.  Before we get into the heart of the <em>how</em> and, more importantly <strong>why</strong> of COMP, it's probably most instructive to look at a simple component based on COMP first.</p>
<h2 id="babys-first-component-heartbeat">Baby's first component: heartbeat</h2>
<p>Heartbeat is a component that just blinks a LED.  It's a "blinky" in short, and thus the "Hello, world!" of embedded systems.  It is, however, an instructive component anyway because heartbeats are very real things in some systems: a pacifying blinking LED that shows the system is powered and active.</p>
<p>Here's the file <code>heartbeat.h</code>:</p>
<pre><code class="language-C">#ifndef HEARTBEAT_H_DEFINED
#define HEARTBEAT_H_DEFINED

COMP_DECLARE(HEARTBEAT);

#define HEARTBEAT_STACK_SIZE    32

#endif
</code></pre>
<p>And here's the file <code>heartbeat.c</code>:</p>
<pre><code class="language-C">#include &quot;bsp.h&quot;

#include &quot;heartbeat.h&quot;

COMP_DEFINE(HEARTBEAT, HEARTBEAT_STACK_SIZE);

static void HEARTBEAT_pump_x_init(void *data)
{
    UNUSED(data);

    bsp_initialize_led();   // BSP function to configure the GPIO pin for the LED
    bsp_led_on();           // BSP function to turn the LED on

    evq_resume_every(HEARTBEAT_queue, HEARTBEAT_co, NULL, 500);
}

static comp_body_t HEARTBEAT_pump_x_body(void *data)
{
    UNUSED(data);

    bsp_led_toggle();       // BSP function to flip the LED's GPIO state between on and off

    return COMP_CONTINUE;
}

static void HEARTBEAT_pump_x_terminate(void *data)
{
    UNUSED(data);

    bsp_led_off();          // BSP function to turn the LED off
}
</code></pre>
<p>And finally here's the <code>main.c</code> file:</p>
<pre><code class="language-C">#include &lt;stdio.h&gt;

#include &quot;co.h&quot;
#include &quot;evq.h&quot;
#include &quot;comp.h&quot;

#include &quot;bsp.h&quot;

#include &quot;heartbeat.h&quot;

int main(int argc, char **argv)
{
    UNUSED(argc);
    UNUSED(argv);

    bsp_initialize();   // BSP function to initialize MCU, tick, etc.

    evq_queue_t main_queue = evq_create_queue();
    HEARTBEAT_init(main_queue, NULL);

    evq_process(main_queue, NULL);

    // we should never reach here, but suppress a warning
    return 0;
}
</code></pre>
<p>And there we have Blinky, COROS-style.  There's a few things to note:</p>
<ol>
<li>We assume a "BSP" library that provides the raw, low-level hardware functions that are meaningful to our higher-level abstractions: system clock configuration, tick configuration, GPIO configuration, GPIO state changes, the <code>evq_get_tick()</code> function implementation, etc.</li>
<li>The mainline code first creates an event queue <code>main_queue</code> which it then passes to a function called <code>HEARTBEAT_init()</code> ... a function that is nowhere visible in the source code.</li>
<li>The mainline code then just processes messages and never stops.</li>
<li>The HEARTBEAT header only calls a macro and sets a stack size macro.</li>
<li>The HEARTBEAT implementation file calls a macro and then defines three weird-looking functions.</li>
<li>The <code>HEARTBEAT_pump_x_init()</code> function initializes the LED hardware, turns on the LED, and sets up a repeating event.</li>
<li>The <code>HEARTBEAT_pump_x_body()</code> function just toggles the LED and returns an inexplicable value.</li>
<li>The <code>HEARTBEAT_pump_x_terminate()</code> function turns off the LED.</li>
</ol>
<p>And yet, somehow, despite there being no obvious link between the various pieces, as well as the mysterious use of functions not in evidence in source, this is actually how a Blinky in COROS would look.</p>
<p>What gives?</p>
<h2 id="what-precisely-is-a-component">What, precisely, is a "component"?</h2>
<p>What gives is that HEARTBEAT is a COROS "component" in COMP style.  So what is a component?  In its most basic, literal form, a component is any block of software that implements these three functions with the correct semantics:</p>
<ul>
<li><code>&lt;name&gt;_activate()</code></li>
<li><code>&lt;name&gt;_deactivate()</code></li>
<li><code>&lt;name&gt;_init()</code></li>
</ul>
<p>None of which are in evidence in the supplied code because COMP provides convenience macros and the convenience macro call in <code>heartbeat.h</code> declares these three functions for us:</p>
<pre><code class="language-C">COMP_DECLARE(HEARTBEAT);
</code></pre>
<p>This macro provides us with an event queue (HEARTBEAT_queue), a coroutine (HEARTBEAT_co), and gives us the declaration of these three functions:</p>
<pre><code class="language-C">extern void HEARTBEAT_activate(void);
extern void HEARTBEAT_deactivate(void);
extern void HEARTBEAT_init(evq_queue_t, void *);
</code></pre>
<p>Further, the call to <code>COMP_DEFINE(HEARTBEAT, HEARTBEAT_STACK_SIZE);</code> provides us with implementation of these three functions.  This is why we can call <code>HEARTBEAT_init()</code> in <code>main()</code>.</p>
<h3 id="is-that-really-all-there-is">Is that really all there is?</h3>
<p>This is actually the most reductive, and least useful, definition of what a component is.  A full-fledged component has a bit more than just these three functions.  A fully-fledged component will have:</p>
<ul>
<li>The three functions mentioned above.</li>
<li>An additional set of API functions in the header for communicating with and controlling the components.  (Not needed in HEARTBEAT so not there.)</li>
<li>A coroutine.  (HEARTBEAT_co in the example, which you can see in the event posting code.)</li>
<li>An event queue.  (HEARTBEAT_queue int he example, which you can again see in the event posting code.)</li>
<li>A message pump implemented in the component's coroutine.</li>
</ul>
<h3 id="message-what-now">Message what now?</h3>
<p>That last item, the message pump, is expressed in three user-supplied callbacks (the "x" convention meaning "external", a fairly common naming convention for user-supplied callbacks):</p>
<ul>
<li><code>HEARTBEAT_pump_x_init()</code></li>
<li><code>HEARTBEAT_pump_x_body()</code></li>
<li><code>HEARTBEAT_pump_x_terminate()</code></li>
</ul>
<p>Sharp eyes will spot that these three correspond to something they've seen before in <a href="../01_coroutines/#coroutine-life-cycles"><em>The Hitchhiker's Guide to Coroutines</em></a>.  These three functions correspond to the coroutine life cycle:</p>
<blockquote>
<ol>
<li>Initialization.</li>
<li>Operation.</li>
<li>Termination.</li>
</ol>
</blockquote>
<p>In fact the "message pump" function provided by the <code>COMP_DEFINE()</code> macro looks like this (cleaned up a bit for pedagogical purposes):</p>
<pre><code class="language-C">static void HEARTBEAT_pump(void *data)
{
    HEARTBEAT_pump_x_init(data);

    do
    {
        data = co_yield(data);
    } while (HEARTBEAT_pump_x_body(data) == COMP_CONTINUE);

    HEARTBEAT_pump_x_terminate(data);
}
</code></pre>
<p>When that pump is viewed, it echoes precisely the life cycle of a coroutine and the three callbacks are the hotspots where user logic is inserted.</p>
<h3 id="anything-else">Anything else?</h3>
<p><a href="../../reference/03_comp/"><em>The Technocrat's Guide to Components</em></a> goes into far greater detail and is mandatory reading for understanding COMP.  A brief summary is that in addition to providing implementations for the mandatory three functions, as well as a message pump with user callbacks, the helper macro also provides the following primitive operations:</p>
<ul>
<li>A function to perform an operation similar to a "call" of the component's coroutine.</li>
<li>A function to send a message to the component's message queue.</li>
<li>A function to generically signal the component through its message queue (no data sent).</li>
<li>A function to yield to the component.</li>
<li>A function to perform a non-blocking delay.</li>
</ul>
<p>These functions are used to implement the exposed API functions, again performing some tedious book-keeping functionality in consistent and disciplined ways.</p>
<h2 id="a-more-realistic-heartbeat">A more realistic heartbeat</h2>
<p>The full <code>COMP_DECLARE()</code> / <code>COMP_DEFINE()</code> facility is actually overkill for a heartbeat.  The macros are provided for the common case of large, complicated components with a lot of functionality and an API.  HEARTBEAT doesn't have this.  A lightweight version might look like this:</p>
<p>Here's the new <code>heartbeat.h</code>:</p>
<pre><code class="language-C">#ifndef HEARTBEAT_H_DEFINED
#define HEARTBEAT_H_DEFINED

COMP_DECLARE(HEARTBEAT);

#endif
</code></pre>
<p>The new <code>heartbeat.c</code> will be more like this:</p>
<pre><code class="language-C">#include &quot;bsp.h&quot;

#include &quot;heartbeat.h&quot;

static evq_queue_t HEARTBEAT_main_queue;
static evq_event_t HEARTBEAT_event;

static void HEARTBEAT_cb(void *data);

void HEARTBEAT_activate(void)
{
    bsp_led_on();

    evq_post_event(HEARTBEAT_main_queue, HEARTBEAT_event);
}

void HEARTBEAT_deactivate(void)
{
    bsp_led_off();

    evq_cancel_event(HEARTBEAT_event);
}

void HEARTBEAT_init(evq_queue_t m, void *data)
{
    UNUSED(data);

    bsp_initialize_led();

    HEARTBEAT_main_queue = m;
    HEARTBEAT_event = evq_create_fn_event(500, 500, HEARTBEAT_cb, NULL);
    HEARTBEAT_activate();
}

static void HEARTBEAT_cb(void *data)
{
    UNUSED(data);

    bsp_led_toggle();
}
</code></pre>
<p>Despite the serious modification of the implementation of HEARTBEAT, the <code>main.c</code> file remains unchanged.</p>
<h3 id="what-have-you-done">What have you done!?</h3>
<p>So what have we changed?</p>
<ol>
<li>We have completely eliminated the unnecessary private event queue and coroutine, piggy-backing instead on the passed-in main queue.</li>
<li>We do not use a message pump, and thus have no callbacks to provide.</li>
<li>We have manually implemented the three mandatory functions.</li>
<li>We are using a callback event for the trivial functionality of flipping a GPIO bit.</li>
<li>Activation of the component entails posting the periodic event; deactivation entails removing the periodic event.</li>
</ol>
<p>This is, in terms of code size (both in C code and in underlying object code) a far more compact implementation of a heartbeat component.</p>
<h3 id="so-whats-the-point">So what's the point?</h3>
<p>The point is that COMP is an <em>architectural framework</em> and not a rigid way of constructing things.  At the beginning when I said a component is anything that implements three function, <strong>I was not joking</strong>.  As we can see here, you can fully run a component in COROS by just implementing the three mandatory functions (plus local logic, naturally, performing the actual operations).  <code>COMP_DEFINE()</code> is just a convenience macro for beefier components.  Which, naturally, we will get to next.</p>
<h2 id="this-is-why-we-have-comp_define">This is why we have COMP_DEFINE()</h2>
<p>Let's talk now about a non-trivial component to explain why we would have all the ceremony around <code>COMP_DEFINE()</code>.  Let's consider a component that has state, has an API, and provides longer-term functionality.  Let's consider a logging facility.</p>
<p>Here's the <code>logger.h</code> file:</p>
<pre><code class="language-C">#ifndef LOGGER_H_DEFINED
#define LOGGER_H_DEFINED

/* exposed macros and constants */
#define LOGGER_STACK_SIZE   256

/* declare the component */
COMP_DECLARE(LOGGER);

/* declare the API for the logger */
extern

#endif
</code></pre>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../../reference/01_co/" class="btn btn-neutral float-right" title="co.h">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="../02_event_queues/" class="btn btn-neutral" title="Event Queues"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
      
      
        <span><a href="../02_event_queues/" style="color: #fcfcfc;">&laquo; Previous</a></span>
      
      
        <span style="margin-left: 15px"><a href="../../reference/01_co/" style="color: #fcfcfc">Next &raquo;</a></span>
      
    </span>
</div>
    <script>var base_url = '../..';</script>
    <script src="../../js/theme.js" defer></script>
      <script src="../../search/main.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>
